package api

import (
	"bufio"
	"bytes"
	"crypto/tls"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"strings"
	"time"

	"gitverse.ru/EYMikhievich/api-gigachat/internal/modules/clientGigaChat/domain"
)

type GigaChatClient struct {
	APIKey     string
	BaseURL    string
	HTTPClient *http.Client
}

func NewGigaChatClient(apiKey, baseURL string) *GigaChatClient {
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	return &GigaChatClient{
		APIKey:     apiKey,
		BaseURL:    baseURL,
		HTTPClient: &http.Client{Transport: tr, Timeout: 10 * time.Second},
	}
}

func (c *GigaChatClient) ChatRequest(req domain.ChatRequest, stream chan string) error {
	url := fmt.Sprintf("%s/v1/chat/completions", c.BaseURL)

	requestBody, err := json.Marshal(req)
	if err != nil {
		return err
	}

	httpReq, err := http.NewRequest("POST", url, bytes.NewBuffer(requestBody))
	if err != nil {
		return err
	}

	httpReq.Header.Set("Content-Type", "application/json")
	httpReq.Header.Set("Authorization", fmt.Sprintf("Bearer %s", c.APIKey))

	resp, err := c.HTTPClient.Do(httpReq)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	if req.Stream {
		reader := bufio.NewReader(resp.Body)
		for {
			line, err := reader.ReadString('\n')
			if err != nil {
				if err == io.EOF {
					break
				}
				return fmt.Errorf("Ошибка при чтении строки: %v", err)
			}

			if strings.HasPrefix(line, "data:") {
				jsonData := strings.TrimSpace(line[5:])
				if jsonData == "[DONE]" {
					break
				}

				var streamResponse domain.StreamChatResponse
				err := json.Unmarshal([]byte(jsonData), &streamResponse)
				if err != nil {
					return fmt.Errorf("Ошибка декодирования ответа потока: %v", err)
				}

				for _, choice := range streamResponse.Choices {
					stream <- choice.Delta.Content
				}
			}
		}
	} else {
		bodyBytes, _ := io.ReadAll(resp.Body)

		var chatResponse domain.ChatResponse
		err := json.Unmarshal(bodyBytes, &chatResponse)
		if err != nil {
			return fmt.Errorf("Ошибка декодирования ответа: %v", err)
		}

		for _, choice := range chatResponse.Choices {
			stream <- choice.Message.Content
		}
	}

	return nil
}
